import {
  Controller,
  Post,
  Get,
  Delete,
  Param,
  Body,
  UseGuards,
  UseInterceptors,
  UploadedFile,
  UploadedFiles,
  Query,
  Logger,
  ParseUUIDPipe
} from '@nestjs/common'
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express'
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiConsumes, ApiBody } from '@nestjs/swagger'
import { UploadService } from './upload.service'
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'
import { CurrentUser } from '../auth/decorators/current-user.decorator'
import type { AuthUser } from '../auth/interfaces/jwt-payload.interface'
import { UploadDto, ImageProcessDto } from './dto/upload.dto'

/**
 * 文件上传控制器
 * 处理文件上传、图片处理、文件管理等HTTP请求
 */
@ApiTags('文件上传')
@Controller('upload')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class UploadController {
  private readonly logger = new Logger(UploadController.name)

  constructor(private readonly uploadService: UploadService) {}

  /**
   * 上传单个文件
   */
  @Post('file')
  @UseInterceptors(FileInterceptor('file'))
  @ApiOperation({ summary: '上传单个文件' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        file: {
          type: 'string',
          format: 'binary',
          description: '要上传的文件'
        },
        type: {
          type: 'string',
          enum: ['image', 'document', 'video', 'audio', 'other'],
          description: '文件类型'
        },
        description: {
          type: 'string',
          description: '文件描述'
        },
        tags: {
          type: 'string',
          description: '文件标签，多个标签用逗号分隔'
        }
      },
      required: ['file']
    }
  })
  @ApiResponse({
    status: 201,
    description: '上传成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '上传成功' },
        data: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            originalName: { type: 'string' },
            filename: { type: 'string' },
            filePath: { type: 'string' },
            url: { type: 'string' },
            mimeType: { type: 'string' },
            size: { type: 'number' },
            type: { type: 'string' },
            createdAt: { type: 'string' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 400, description: '请求参数错误' })
  @ApiResponse({ status: 401, description: '未授权' })
  async uploadFile(
    @UploadedFile() file: Express.Multer.File,
    @Body() uploadDto: UploadDto,
    @CurrentUser() user: AuthUser
  ) {
    try {
      const result = await this.uploadService.uploadFile(
        file,
        user.id,
        uploadDto.type,
        uploadDto.description,
        uploadDto.tags
      )

      this.logger.log(`文件上传成功: ${file.originalname} by ${user.username}`)

      return {
        success: true,
        message: '上传成功',
        data: result
      }
    } catch (error) {
      this.logger.error(`文件上传失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 上传并处理图片
   */
  @Post('image')
  @UseInterceptors(FileInterceptor('file'))
  @ApiOperation({ summary: '上传并处理图片' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        file: {
          type: 'string',
          format: 'binary',
          description: '要上传的图片文件'
        },
        width: {
          type: 'number',
          description: '图片宽度'
        },
        height: {
          type: 'number',
          description: '图片高度'
        },
        quality: {
          type: 'number',
          description: '图片质量 (1-100)'
        },
        format: {
          type: 'string',
          enum: ['jpeg', 'png', 'webp', 'avif'],
          description: '输出格式'
        },
        description: {
          type: 'string',
          description: '文件描述'
        },
        tags: {
          type: 'string',
          description: '文件标签，多个标签用逗号分隔'
        }
      },
      required: ['file']
    }
  })
  @ApiResponse({
    status: 201,
    description: '上传成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '上传成功' },
        data: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            originalName: { type: 'string' },
            filename: { type: 'string' },
            filePath: { type: 'string' },
            url: { type: 'string' },
            mimeType: { type: 'string' },
            size: { type: 'number' },
            type: { type: 'string' },
            createdAt: { type: 'string' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 400, description: '请求参数错误' })
  @ApiResponse({ status: 401, description: '未授权' })
  async uploadImage(@UploadedFile() file: Express.Multer.File, @Body() body: any, @CurrentUser() user: AuthUser) {
    try {
      const processOptions: ImageProcessDto = {
        width: body.width ? parseInt(body.width) : undefined,
        height: body.height ? parseInt(body.height) : undefined,
        quality: body.quality ? parseInt(body.quality) : undefined,
        format: body.format
      }

      const result = await this.uploadService.uploadImage(file, user.id, processOptions, body.description, body.tags)

      this.logger.log(`图片上传成功: ${file.originalname} by ${user.username}`)

      return {
        success: true,
        message: '上传成功',
        data: result
      }
    } catch (error) {
      this.logger.error(`图片上传失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 批量上传文件
   */
  @Post('files')
  @UseInterceptors(FilesInterceptor('files', 10)) // 最多10个文件
  @ApiOperation({ summary: '批量上传文件' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        files: {
          type: 'array',
          items: {
            type: 'string',
            format: 'binary'
          },
          description: '要上传的文件列表'
        },
        type: {
          type: 'string',
          enum: ['image', 'document', 'video', 'audio', 'other'],
          description: '文件类型'
        },
        description: {
          type: 'string',
          description: '文件描述'
        },
        tags: {
          type: 'string',
          description: '文件标签，多个标签用逗号分隔'
        }
      },
      required: ['files']
    }
  })
  @ApiResponse({
    status: 201,
    description: '上传成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '上传成功' },
        data: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              id: { type: 'string' },
              originalName: { type: 'string' },
              filename: { type: 'string' },
              filePath: { type: 'string' },
              url: { type: 'string' },
              mimeType: { type: 'string' },
              size: { type: 'number' },
              type: { type: 'string' },
              createdAt: { type: 'string' }
            }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 400, description: '请求参数错误' })
  @ApiResponse({ status: 401, description: '未授权' })
  async uploadFiles(
    @UploadedFiles() files: Express.Multer.File[],
    @Body() uploadDto: UploadDto,
    @CurrentUser() user: AuthUser
  ) {
    try {
      const results = await Promise.all(
        files.map(file =>
          this.uploadService.uploadFile(file, user.id, uploadDto.type, uploadDto.description, uploadDto.tags)
        )
      )

      this.logger.log(`批量文件上传成功: ${files.length} 个文件 by ${user.username}`)

      return {
        success: true,
        message: '上传成功',
        data: results
      }
    } catch (error) {
      this.logger.error(`批量文件上传失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 获取文件信息
   */
  @Get(':id')
  @ApiOperation({ summary: '获取文件信息' })
  @ApiResponse({
    status: 200,
    description: '获取成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '获取成功' },
        data: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            originalName: { type: 'string' },
            filename: { type: 'string' },
            filePath: { type: 'string' },
            url: { type: 'string' },
            mimeType: { type: 'string' },
            size: { type: 'number' },
            type: { type: 'string' },
            description: { type: 'string' },
            tags: { type: 'string' },
            uploadedBy: {
              type: 'object',
              properties: {
                id: { type: 'string' },
                username: { type: 'string' },
                nickname: { type: 'string' }
              }
            },
            createdAt: { type: 'string' },
            updatedAt: { type: 'string' }
          }
        }
      }
    }
  })
  @ApiResponse({ status: 404, description: '文件不存在' })
  @ApiResponse({ status: 401, description: '未授权' })
  async getFileInfo(@Param('id', ParseUUIDPipe) id: string) {
    try {
      const result = await this.uploadService.getFileInfo(id)

      return {
        success: true,
        message: '获取成功',
        data: result
      }
    } catch (error) {
      this.logger.error(`获取文件信息失败: ${error.message}`, error.stack)
      throw error
    }
  }

  /**
   * 删除文件
   */
  @Delete(':id')
  @ApiOperation({ summary: '删除文件' })
  @ApiResponse({
    status: 200,
    description: '删除成功',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean', example: true },
        message: { type: 'string', example: '删除成功' }
      }
    }
  })
  @ApiResponse({ status: 404, description: '文件不存在' })
  @ApiResponse({ status: 403, description: '无权限删除' })
  @ApiResponse({ status: 401, description: '未授权' })
  async deleteFile(@Param('id', ParseUUIDPipe) id: string, @CurrentUser() user: AuthUser) {
    try {
      await this.uploadService.deleteFile(id, user.id)

      this.logger.log(`文件删除成功: ${id} by ${user.username}`)

      return {
        success: true,
        message: '删除成功'
      }
    } catch (error) {
      this.logger.error(`文件删除失败: ${error.message}`, error.stack)
      throw error
    }
  }
}
